package org.dut.community.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.dut.community.dao.DiscussPostMapper;
import org.dut.community.entity.DiscussPost;
import org.dut.community.util.CommunityConstant;
import org.dut.community.util.MarkdownUtils;
import org.dut.community.util.RedisKeyUtil;
import org.dut.community.util.SensitiveFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.util.HtmlUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;


@Service
public class DiscussPostService implements CommunityConstant {
    @Autowired
    private DiscussPostMapper discussPostMapper;
    @Autowired
    private SensitiveFilter sensitiveFilter;
    @Autowired
    private RedisTemplate redisTemplate;

    public List<DiscussPost> selectDiscussPosts(int userId, int offset, int limit, int orderMode) {
        return discussPostMapper.selectDiscussPosts(userId, offset, limit, orderMode);
    }

    public int selectDiscussPostRows(@Param("userId") int userId) {
        return discussPostMapper.selectDiscussPostRows(userId);
    }

    public int addDiscussPost(DiscussPost post) {
        checkAndHandlePost(post);
        return discussPostMapper.insertDiscussPost(post);
    }


    public DiscussPost findDiscussPostById(int id) {
        DiscussPost discussPost = discussPostMapper.selectDiscussPostById(id);
        if (discussPost != null) {
            // 转换为markdown格式
            discussPost.setContent(MarkdownUtils.markdownToHtml(discussPost.getContent()));
        }
        return discussPost;
    }

    public void updateDiscussPost(DiscussPost discussPost) {
        checkAndHandlePost(discussPost);
        discussPostMapper.updateDiscussPost(discussPost.getId(),
                discussPost.getTitle(), discussPost.getContent(), discussPost.getCreateTime());
    }

    private void checkAndHandlePost(DiscussPost discussPost) {
        if (discussPost == null) {
            throw new IllegalArgumentException("参数不能为空！");
        }
        discussPost.setTitle(HtmlUtils.htmlEscape(discussPost.getTitle()));
        discussPost.setContent(HtmlUtils.htmlEscape(discussPost.getContent()));
        discussPost.setTitle(sensitiveFilter.filter(discussPost.getTitle()));
        discussPost.setContent(sensitiveFilter.filter(discussPost.getContent()));
    }

    public int updateCommentCount(int id, int commentCount) {
        return discussPostMapper.updateCommentCount(id, commentCount);
    }

    // 获取帖子阅读量，旁路缓存
    public int getPostReadCount(int postId) {
        String redisKey = RedisKeyUtil.getPostReadKey(postId);
        Object readCountObj = redisTemplate.opsForValue().get(redisKey);
        if (readCountObj instanceof Integer) {
            return (Integer) readCountObj;
        } else {
            readCountObj = discussPostMapper.selectPostReadCount(postId);
            redisTemplate.opsForValue().set(redisKey, readCountObj);
            return (Integer) readCountObj;
        }
    }

    // 在redis中增加帖子的阅读量
    public void updatePostReadCount(int postId) {
        String redisKey = RedisKeyUtil.getPostReadKey(postId);
        // 如果键不存在，则从数据库获取初值
        Object readCountObj = redisTemplate.opsForValue().get(redisKey);
        if (readCountObj == null) {
            DiscussPost post = discussPostMapper.selectDiscussPostById(postId);
            if (post != null) {
                redisTemplate.opsForValue().set(redisKey, post.getReadCount());
            } else {
                redisTemplate.opsForValue().set(redisKey, 0);
            }
        }
        // 增加访问量
        redisTemplate.opsForValue().increment(redisKey);
    }

    // 更新数据库中的阅读量
    public void updatePostReadCountInDatabase() {
        List<DiscussPost> posts = discussPostMapper.selectAllDiscussPosts();
        for (DiscussPost post : posts) {
            String redisKey = RedisKeyUtil.getPostReadKey(post.getId());
            Object readCountObj = redisTemplate.opsForValue().get(redisKey);
            if (readCountObj instanceof Integer) {
                Integer readCount = (Integer) readCountObj;
                discussPostMapper.updateReadCount(post.getId(), readCount);
                redisTemplate.delete(redisKey);
            }
        }
    }

    public int updateType(int id, int type) {
        return discussPostMapper.updateType(id, type);
    }

    public int updateStatus(int id, int status) {
        return discussPostMapper.updateStatus(id, status);
    }

    // 找到被删除的帖子
    public List<DiscussPost> selectDeletedDiscussPosts(int userId) {
        return discussPostMapper.selectDeletedDiscussPosts(userId);
    }

    public void updateScore(int postId, double score) {
        discussPostMapper.updateScore(postId, score);
    }

    // 关注者的帖子
    public List<DiscussPost> selectFolloweePosts(int userId, int offset, int limit) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        Set<Integer> followeeIds = redisTemplate.opsForZSet().range(followeeKey, 0, -1);
        if (followeeIds == null) {
            return null;
        } else {
            List<Integer> followeeIdList = new ArrayList<>(followeeIds);
            if (followeeIdList.isEmpty()) {
                return null;
            } else {
                return discussPostMapper.selectFolloweePosts(followeeIdList, offset, limit);
            }
        }
    }

    // 关注者帖子的数量
    public int findFolloweePostCount(int userId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        Set<Integer> followeeIds = redisTemplate.opsForZSet().range(followeeKey, 0, -1);
        if (followeeIds == null) {
            return 0;
        }
        int cnt = 0;
        for (Integer followeeId : followeeIds) {
            cnt += discussPostMapper.selectDiscussPostRows(followeeId);
        }
        return cnt;
    }

    // 某人所有的帖子，不分页
    public List<DiscussPost> selectUserPosts(int userId) {
        return discussPostMapper.selectUserPosts(userId);
    }

    // 通知粉丝有未读帖子 , follower 发布新帖子时触发
    public void notifyFollowersNewPost(int userId, int postId) {
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        Set<Integer> followerIds = redisTemplate.opsForZSet().range(followerKey, 0, -1);

        if(followerIds != null) {
            for(Integer followerId:followerIds) {
                String postUnreadKey = RedisKeyUtil.getFolloweePostUnreadKey(followerId);
                redisTemplate.opsForZSet().add(postUnreadKey,postId,System.currentTimeMillis());
            }
        }
    }

    // 检查是否有未读帖子
    public boolean hasUnreadPosts(int userId) {
        String unreadKey = RedisKeyUtil.getFolloweePostUnreadKey(userId);
        Long unreadCount = redisTemplate.opsForZSet().zCard(unreadKey);
        return unreadCount != null && unreadCount > 0;
    }

    // 标记帖子已读
    public void markPostsAsRead(int userId) {
        String unreadKey = RedisKeyUtil.getFolloweePostUnreadKey(userId);
        redisTemplate.delete(unreadKey);
    }
}
